package design.patterns.proxymode.dynamicProxy.proxy_Spring_AOP;

import common.util.FileUrlReader;
import design.patterns.proxymode.dynamicProxy.service.IAdviceImpl;

import java.io.*;
import java.util.Properties;

import static java.lang.System.out;

/**
 * 一个专门生产javaBean的工厂
 * @Description :
 * @author: cww
 * @DateTime: 2018-07-26 23:15
 */

public class BeanFactory {
    /**
     * 第一步，读取配置文件
     * 构造函数接收一个配置文件流
     */
    private Properties properties = new Properties();
    public BeanFactory(String filePath) throws IOException {
        InputStream inputStream = null;
        try {
            FileUrlReader fileUrlReader = new FileUrlReader();
            String url = fileUrlReader.getFileUrlFromClassPath(filePath);
            inputStream = new BufferedInputStream(new FileInputStream(url));
            InputStreamReader reader = new InputStreamReader(inputStream,"UTF-8");
            properties.load(reader);
        } catch (IOException e) {
            out.println("读取配置文件异常");
            e.printStackTrace();
        }finally {
            inputStream.close();
        }
    }

    /**
     * NO.2
     * 接收一个字符串，通过这个字符串到配置文件中对应的java类名
     * 判断是否为ProxyFactoryBean
     * @param name
     * @return
     */
    public Object getBean(String name){
        String className = properties.getProperty(name);
        try {
            //通过classname获取Class字节码
            Class clazz = Class.forName(className);
            //调用不带参数的构造方法创建bean实例，这就是javaBean的特性，必须要有一个不带参数的构造方法，因为在创建javaBean时候必须要调用无参的构造函数 ！！！！
            Object bean = clazz.newInstance();
            //检查这个bean是否是ProxyFactoryBean类型
            if (bean instanceof ProxyFactoryBean){
                out.println("根据"+name+"产生的javaBean属于ProxyFactory");
                out.println("开始创建"+bean+"的代理");

                //用ProxyFactoryBean来创建一个代理对象(创建代理对象在getProxy()方法内部进行的)，并返回代理
                Object o;
                //读取配置文件中对应的javaBean对象的名字，再使用class.forName()方法获取字节码,再用newInstance()获取实例对象
                ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean) bean;
                //与上面一下通过名字获取javaBean实例对象，两种方法
                IAdviceImpl iAdvice = (IAdviceImpl) Class.forName(properties.getProperty(name+".advice")).newInstance();
                Object target = Class.forName((String) properties.get(name+".target")).newInstance();
                //传入代理中需要用到的目标对象与业务代码
                proxyFactoryBean.setiAdvice(iAdvice);
                proxyFactoryBean.setTarget(target);
                //最后获取代理对象并返回
                o = proxyFactoryBean.getProxy();
                return o;
            } else {
                out.println("根据"+name+"产生的javaBean不属于ProxyFactory");
                return bean;
            }
        } catch (ClassNotFoundException e) {
            out.println("获取类名为"+className+"的Class字节码失败");
            e.printStackTrace();
        } catch (InstantiationException e) {
            out.println("创建类名为"+className+"的实例异常:"+e.getMessage());
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            out.println("创建类名为"+className+"的实例异常："+e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

}
